#!/usr/bin/ksh
#
# diskhits - disk access by file offset.
#            Written using DTrace (Solaris 10 3/05).
#
# $Id: diskhits 3 2007-08-01 10:50:08Z brendan $
#
# This prints how a file was accessed, the locations on a distribution plot.
# This is for the cache misses only - the file activity that resulted in
# disk events.
#
# USAGE:	diskhits pathname
#	eg,
#		diskhits /var/adm/messages
#
# FIELDS:
#		Location (KB)	The file offset of the disk activity, Kbytes.
#		Size (KB)	Size of the disk activity, Kbytes.
#		Total RW	Total disk activity, reads + writes.
#
# BASED ON: /usr/demo/dtrace/applicat.d
#
# SEE ALSO: DTrace Guide "io Provider" chapter (docs.sun.com)
#           iosnoop (DTraceToolkit)
#
# PORTIONS: Copyright (c) 2005, 2006 Brendan Gregg.
#
# CDDL HEADER START
#
#  The contents of this file are subject to the terms of the
#  Common Development and Distribution License, Version 1.0 only
#  (the "License").  You may not use this file except in compliance
#  with the License.
#
#  You can obtain a copy of the license at Docs/cddl1.txt
#  or http://www.opensolaris.org/os/licensing.
#  See the License for the specific language governing permissions
#  and limitations under the License.
#
# CDDL HEADER END
#
# 08-Jun-2005   Brendan Gregg   Created this.
# 20-Apr-2006	   "      "	Last update.
#

### Usage
function usage
{
	cat <<-END >&2
	USAGE: diskhits pathname
	   eg,
	       diskhits /var/adm/wtmpx
	END
	exit 1
}

### Process arguments
if (( $# != 1 )); then
	usage
fi
if [[ $1 == "-h" ]]; then
	usage
fi
pathname=$1
if [[ ! -e $pathname ]]; then
	print "ERROR2: file $pathname not found" >&2
	exit 2
fi

### Calculate output scale
report_lines=20
set -- `ls -l $pathname`
filesize=$5
(( file_kb_max = filesize / 1024 ))
(( scale_kb = filesize / (1024 * report_lines) ))
if (( file_kb_max < 20 )); then file_kb_max=20; fi
if (( scale_kb < 1 )); then scale_kb=1; fi

#
#  Run DTrace
#
/usr/sbin/dtrace -n '
 #pragma D option quiet

 inline string PATHNAME = "'$pathname'";
 inline int FILE_KB_MAX = '$file_kb_max';
 inline int SCALE_KB = '$scale_kb';

 dtrace:::BEGIN
 {
	printf("Tracing... Hit Ctrl-C to end.\n");
 }

 io:::start
 /args[2]->fi_pathname == PATHNAME/
 {
	this->kb = args[2]->fi_offset == -1 ? -1 : args[2]->fi_offset / 1024;
	@Location = lquantize(this->kb, 0, FILE_KB_MAX, SCALE_KB);
	@Size = quantize(args[0]->b_bcount/1024);
	@Total = sum(args[0]->b_bcount/1024);
 }

 dtrace:::END
 {
	printf("Location (KB),");
	printa(@Location);

	printf("Size (KB),");
	printa(@Size);

	printa("Total RW: %@d KB\n", @Total);
 }
'
